import React, { Fragment, PureComponent } from 'react';
import { connect } from 'react-redux';
import { array, func } from 'prop-types';
import * as HomeActions from '@/actions/home';
import ListItem from '../../components/listItem/ListItem';
import RecommandItem from '../../components/recommandItem/RecommandItem';
import Spin from '../../components/spin/Spin';
import Input from '../../components/input/Input';
import './Home.less';

class Home extends PureComponent {
  static propTypes = {
    grossingAppsList: array.isRequired,
    grossing10AppsList: array.isRequired,
    top100List: array.isRequired,
    top10List: array.isRequired,
    getTop10GrossingApps: func.isRequired,
    getTopGrossingApps: func.isRequired,
    getTopFreeApps: func.isRequired,
    getTop10FreeApps: func.isRequired,
  };

  state = {
    hasMore: true, // 是否还有更多
    page: 1, // 请求加载数据数
    isSearch: false, // 搜索状态
    MatchedTopFreeAppList: [], // 满足搜索的列表数据
    topAppsPageList: [], // 分页的列表数据
    grossingApps: [], // 推荐app数据
    loading: false, // 数据加载loading状态
  };

  /**
   * 获取top100
   */
  getTopFreeApps = async () => {
    this.setState({ loading: true });
    await this.props.getTop10FreeApps(); // 先获取第一页数据top10，页面渲染后再获取top100
    this.setState({ loading: false });
    await this.props.getTopFreeApps(); // 获取top100
    await this.props.getTopGrossingApps(); // 获取100个推荐，用于搜索匹配
  };

  getTopFreeAppsByPage = () => {
    const { page, topAppsPageList, MatchedTopFreeAppList } = this.state;
    const startIndex = (page - 1) * 10;
    const topAppsList = topAppsPageList.concat(
      MatchedTopFreeAppList.slice(startIndex, startIndex + 10)
    );
    this.setState({
      topAppsPageList: topAppsList,
    });
  };

  componentDidMount() {
    this.props.getTop10GrossingApps();
    this.getTopFreeApps();
    window.addEventListener('scroll', this.handleScroll);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll);
  }

  UNSAFE_componentWillReceiveProps(nextProps) {
    if (nextProps.top10List.length > 0) {
      this.setState({
        topAppsPageList: nextProps.top10List,
      });
    }
    if (nextProps.grossing10AppsList.length > 0) {
      this.setState({
        grossingApps: nextProps.grossing10AppsList,
      });
    }
    if (nextProps.top100List.length > 0) {
      this.setState({
        MatchedTopFreeAppList: nextProps.top100List,
        topAppsPageList: nextProps.top100List.slice(0,10),
      });
    }
    if (nextProps.grossingAppsList.length > 0) {
      this.setState({
        grossingApps: nextProps.grossingAppsList.slice(0,10),
      });
    }
  }

  /**
   * 滚动监听
   */
  handleScroll = () => {
    const { hasMore, page } = this.state;
    if (!hasMore) {
      return;
    }
    // container距离可视区域顶部的距离
    const top = this.refs.container.getBoundingClientRect().top;
    // container高度
    const height = this.refs.container.offsetHeight;
    if (top + height <= window.screen.height + 100) {
      if (page > 10) {
        this.setState({ hasMore: false });
      }
      this.setState(
        state => ({
          page: state.page + 1,
        }),
        () => this.getTopFreeAppsByPage()
      );
    }
  };

  /**
   * 输入事件
   */
  handleChange = value => {
    const { top100List, grossingAppsList } = this.props;
    this.handleSearch(value);
    if (!value.length) {
      this.setState({
        MatchedTopFreeAppList: top100List,
        grossingApps: grossingAppsList.slice(0, 10),
        isSearch: false,
        hasMore: true,
        page: 1,
      });
    }
  };

  /**
   * 搜索
   * @param {string} val Input输入字符
   */
  handleSearch = val => {
    const { top100List, grossingAppsList } = this.props;
    const str = val.toLowerCase();
    const matchArr = top100List.filter(
      item =>
        item['im:name'].label.toLowerCase().match(str) ||
        item.category.attributes.label.toLowerCase().match(str) ||
        item.summary.label.toLowerCase().match(str)
    );
    const matchGrossing = grossingAppsList.filter(
      item =>
        item['im:name'].label.toLowerCase().match(str) ||
        item.category.attributes.label.toLowerCase().match(str) ||
        item.summary.label.toLowerCase().match(str)
    );
    this.setState(
      {
        isSearch: true,
        MatchedTopFreeAppList: matchArr,
        topAppsPageList: [],
        grossingApps: matchGrossing.slice(0, 10),
        page: 1,
        hasMore: true,
      },
      this.getTopFreeAppsByPage
    );
  };

  render() {
    const {
      topAppsPageList,
      grossingApps,
      hasMore,
      MatchedTopFreeAppList,
      loading,
    } = this.state;

    return (
      <div className="container" ref="container">
        {/* 搜索框 */}
        <div className="search">
          <Input type="search" placeholer="搜索" onChange={this.handleChange} />
        </div>

        {/* 推荐列表 */}
        {!!grossingApps.length && (
          <div className="grossing-list">
            <h2 className="p">推介</h2>
            <div className="grossing-box">
              {grossingApps.map(item => (
                <Fragment key={item.id.attributes['im:id']}>
                  <RecommandItem
                    id={item.id.attributes['im:id']}
                    category={item.category.attributes.label}
                    imageUrl={item['im:image'][1].label}
                    title={item['im:name'].label}
                  />
                </Fragment>
              ))}
            </div>
          </div>
        )}

        {/* top100列表 */}
        <div className="top-list">
          {!!topAppsPageList.length &&
            topAppsPageList.map((item, index) => (
              <Fragment key={item.id.attributes['im:id']}>
                <ListItem
                  serial={index + 1}
                  id={item.id.attributes['im:id']}
                  title={item['im:name'].label}
                  category={item.category.attributes.label}
                  imageUrl={item['im:image'][0].label}
                  rate={2}
                  isOdd={(index + 1) % 2 === 0}
                />
              </Fragment>
            ))}
        </div>

        <Spin spinning={loading} />

        {!hasMore &&
          (!MatchedTopFreeAppList.length ? (
            <div className="no-data">暂无数据</div>
          ) : (
            <div className="no-more">没有更多了...</div>
          ))}
      </div>
    );
  }
}

const mapStateToProps = state => ({
  grossingAppsList: state.home.grossingAppsList,
  grossing10AppsList: state.home.grossing10AppsList,
  top100List: state.home.top100List,
  top10List: state.home.top10List,
});

const mapDispatchToProps = dispatch => ({
  getTop10GrossingApps: () => {
    dispatch(HomeActions.getTop10GrossingApps());
  },
  getTopGrossingApps: () => {
    dispatch(HomeActions.getTopGrossingApps());
  },
  getTopFreeApps: () => {
    dispatch(HomeActions.getTopFreeApps());
  },
  getTop10FreeApps: () => {
    dispatch(HomeActions.getTop10FreeApps());
  },
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Home);
